/**
 * @file sysmanage.c
 * @Synopsis  该文档主要实现设备上的数据保存、数据加载、全局数据管理
 * 等系统特有数据处理。
 * @author SWFighter
 * @version 1.0.0
 * @date 2019-01-02
 */
#include "sysmanage.h"
#include "epd_show.h"
#include <fcntl.h>
#include "stdio.h"
#include "esp_common.h"


devInfodef devInfoDat = {0};
wifiConfigDef wifiConfigDat = {0};

u8_t taskWork = 0;
static u32_t sysdate = 0;


/**
  * @brief  EEPROM 驱动关闭
  * @param  EEPROM 驱动对象
  * @retval None
  */
void eeprom_device_close(void)
{

}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  EEPROM 保存图片数据
 *
 * @Param data  图片地址
 */
/* ----------------------------------------------------------------------------*/
void eeprom_save_data(u8_t *data)
{
	int pfd =  open(PIC_DATA_FILE, O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
	if(pfd <= 3) 
	{
		printf("open %s file error \r\n",PIC_DATA_FILE);
	}
	int write_byte = write(pfd, data, ELS_PIC_BUF_SIZE);
	if (write_byte <= 0)
	{
		printf("write %s file error \r\n",PIC_DATA_FILE);
	}
	close(pfd);
}



/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  EEPROM 加载图片数据
 *
 * @Param data 图片数据缓存
 */
/* ----------------------------------------------------------------------------*/
void eeprom_load_data(u8_t *data)
{
	int pfd =  open(PIC_DATA_FILE, O_RDONLY, S_IRUSR | S_IWUSR);
	if(pfd <= 3) 
	{
	  printf("open %s file error \n",PIC_DATA_FILE);
	}
	int write_byte = read(pfd, data, ELS_PIC_BUF_SIZE);
	if (write_byte != ELS_PIC_BUF_SIZE)
	{
	  printf("read %s file error \n",PIC_DATA_FILE);
	}
	close(pfd);
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  保存带有ID的 图片
 *
 * @Param data
 */
/* ----------------------------------------------------------------------------*/
void eeprom_save_IDdata(u8_t *data)
{
	int pfd =  open(PIC_DEVID_FILE, O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
	if(pfd <= 3) 
	{
		printf("open %s file error \r\n",PIC_DEVID_FILE);
	}
	int write_byte = write(pfd, data, ELS_PIC_BUF_SIZE);
	if (write_byte <= 0)
	{
		printf("write %s file error \r\n",PIC_DEVID_FILE);
	}
	close(pfd);
}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  保存带有ID的图片
 *
 * @Param data
 */
/* ----------------------------------------------------------------------------*/
void eeprom_load_IDdata(u8_t *data)
{
	int pfd =  open(PIC_DEVID_FILE, O_RDONLY, S_IRUSR | S_IWUSR);
	if(pfd <= 3) 
	{
	  printf("open %s file error \n",PIC_DEVID_FILE);
		return ;
	}
	int write_byte = read(pfd, data, ELS_PIC_BUF_SIZE);
	if (write_byte != ELS_PIC_BUF_SIZE)
	{
	  printf("read %s file error \n",PIC_DEVID_FILE);
	}
	close(pfd);
}

void spiffs_erase_format(void)
{
	u32_t i;

	for(i=0; i<250; i++)
	{
		spi_flash_erase_sector(3*256+i);
	}
}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis 获取设备的芯片MAC 
 *
 * @Param id
 */
/* ----------------------------------------------------------------------------*/
void get_dev_mac(u8_t *id)
{
	u32_t CpuID[3];
	
	//获取CPU唯一ID

	CpuID[2] = system_get_chip_id();
	//转换为字节
	uint32_to_str(CpuID[2], &id[8]);
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  加载EEPROM到设备信息结构体
 *
 * @Returns   
 */
/* ----------------------------------------------------------------------------*/
STATUS devinfo_loader(void)
{
	int pfd =  open(DEV_INFO_FILE, O_RDONLY, S_IRUSR | S_IWUSR);
	if(pfd <= 3) 
	{
		printf("open file error \n");
	}
	int write_byte = read(pfd, &devInfoDat, sizeof(devInfoDat));
	if (write_byte != sizeof(devInfoDat))
	{
		printf("read file error \n");
	}
	close(pfd);

	return OK;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  保存设备信息到EEPROM
 *
 * @Returns   
 */
/* ----------------------------------------------------------------------------*/
STATUS devinfo_save(void)
{
	STATUS result;

	result = OK;
	int pfd =  open(DEV_INFO_FILE, O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
	if(pfd <= 3) 
	{
	  printf("open file error \r\n");
		result = FAIL;
	}
	int write_byte = write(pfd, &devInfoDat, sizeof(devInfoDat));
	if (write_byte <= 0)
	{
	  printf("write file error \r\n");
		result = FAIL;
	}
	close(pfd);

	return result;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  获取设备信息结构体
 *
 * @Param data
 */
/* ----------------------------------------------------------------------------*/
devInfodef* devinfo_get(void)
{
	printf("***************************************%s\n",devInfoDat.url);
	return &devInfoDat;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  设置设备信息结构体
 *
 * @Param data
 */
/* ----------------------------------------------------------------------------*/
void devinfo_set(devInfodef *data)
{
	devInfoDat = (*data);
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  保存流量
 */
/* ----------------------------------------------------------------------------*/
void save_sysflow_bkp(void)
{

}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  设置备份寄存器
 *
 * @Param value
 */
/* ----------------------------------------------------------------------------*/
void set_bkp1_reg(u16_t value)
{

}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  价值备份寄存器中的流量（DR3）
 */
/* ----------------------------------------------------------------------------*/
void load_bkp_sys_flow(void)
{

}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis 保存唤醒次数 （DR5）
 *
 * @Param value 寄存器值
 */
/* ----------------------------------------------------------------------------*/
void save_bkp_wakeup_num(u16_t value)
{
	system_rtc_mem_write(RTC_USEADDR3,(const void*)&value,sizeof(value));
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  从备份寄存器中加载唤醒次数
 *
 * @Returns  寄存器的值 
 */
/* ----------------------------------------------------------------------------*/
u16_t load_bkp_wakeup_num(void)
{
	u16_t value;
	
	system_rtc_mem_read(RTC_USEADDR3, (void *)&value, sizeof(value));

	printf("Wakeup Num == %d\r\n",value);
	return value;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  保存备份寄存器查询失败次数
 *
 * @Param value 寄存器值
 */
/* ----------------------------------------------------------------------------*/
void save_bkp_askfail_num(u16_t value)
{
	system_rtc_mem_write(RTC_USEADDR2,(const void*)&value,sizeof(value));
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  加载备份寄存器查询失败次数
 *
 * @Returns  寄存器值 
 */
/* ----------------------------------------------------------------------------*/
u16_t load_bkp_askfail_num(void)
{
	u16_t value;
	
	system_rtc_mem_read(RTC_USEADDR2, (void *)&value, sizeof(value));

	printf("ask fail num == %d\r\n",value);
	return value;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  保存数据倒备份寄存器
 *
 * @Param value
 */
/* ----------------------------------------------------------------------------*/
void save_bkp_surplus_ask_num(u16_t value)
{
	system_rtc_mem_write(RTC_USEADDR4,(const void*)&value,sizeof(value));
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  从备份寄存器加载剩余查询次数
 *
 * @Returns   
 */
/* ----------------------------------------------------------------------------*/
u16_t load_bkp_surplus_ask_num(void)
{
	u16_t value;
	
	system_rtc_mem_read(RTC_USEADDR4, (void *)&value, sizeof(value));

	printf("SurPlus Wakeup Num = %d\r\n",value);
	return value;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  保存当前这次睡眠的值
 *
 * @Param sec 秒
 */
/* ----------------------------------------------------------------------------*/
void save_bkp_deep_sleep_value(u32_t sec)
{
	system_rtc_mem_write(RTC_USEADDR5,(const void*)&sec,sizeof(u32_t));
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  加载当前睡眠的值
 *
 * @Returns  休眠时间 S 
 */
/* ----------------------------------------------------------------------------*/
u32_t load_bkp_deep_sleep_value(void)
{
	u32_t value;
	
	system_rtc_mem_read(RTC_USEADDR5, (void *)&value, sizeof(u32_t));

	printf("Deep Sleep Time = %d\r\n",value);
	return value;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  保存系统事件
 *
 * @Param evt  事件
 */
/* ----------------------------------------------------------------------------*/
void save_system_event(u32_t evt)
{
	system_rtc_mem_write(RTC_USEADDR6,(const void*)&evt,sizeof(u32_t));
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  加载系统事件
 *
 * @Returns   
 */
/* ----------------------------------------------------------------------------*/
u32_t load_system_event(void)
{
	u32_t value;
	
	system_rtc_mem_read(RTC_USEADDR6, (void *)&value, sizeof(u32_t));

	//printf("System Event = %x\r\n",value);
	return value;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  保存系统信息到备份寄存器
 *
 * @Param value 保存值
 */
/* ----------------------------------------------------------------------------*/
void save_bkp_sysinfo(u16_t value)
{
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  从RTC备份寄存器加载系统信息
 *
 * @Returns  加载值 
 */
/* ----------------------------------------------------------------------------*/
u16_t load_bkp_sysinfo(void)
{
}


void set_rtc_system_event_bit(u32_t flag,BOOL data)
{
	u32_t value = 0;

	value = load_system_event();
	if(data == TRUE)//置位
	{
		value |= flag;
	}
	else//清除
	{
		value &= ~flag;
	}
	save_system_event(value);
}

BOOL get_rtc_system_event_bit(u32_t flag)
{
	u32_t value = 0;

	value = load_system_event();
	if(value & flag)
	{
		return TRUE;
	}
	return FALSE;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis 电池开机初始化检测 
 */
/* ----------------------------------------------------------------------------*/
void vbat_init_process(void)
{
	devInfodef *info;
	
	epd_power_pin(1);
	info = devinfo_get();

	info->vbat = get_sys_vbat();//采集电压
	printf("system vbat = %d\r\n",info->vbat);
	if(info->vbat < 5)//电压过低
	{
		BOOL status;
		
		printf("system power too low %d \%\r\n",info->vbat);
		status = get_rtc_system_event_bit(EVT_SHOW_BATLOW);
		if(status == FALSE)//没有显示低电压才重新显示
		{
			send_epd_mail(EPD_EVT_BATAlA);//显示电池欠压标记
		}
	}
}


static BOOL is_refrsh_epd(void)
{
	BOOL status;

	status = get_rtc_system_event_bit(EVT_START_SHOW);
	if(status == TRUE)//如果上次显示没有完成，重新刷新一下屏幕
	{
		send_epd_mail(EPD_EVT_FULL);//整屏显示
	}
	return status;
}


BOOL vbat_low_stop_process(void)
{
	devInfodef *info;
	BOOL status;
	
	epd_power_pin(1);
	info = devinfo_get();

	info->vbat = get_sys_vbat();//采集电压
	if(info->vbat <= 2)
	{
		//没电了不工作
		printf("System Power Too Low Entry Deep Sleep\r\n");
		set_system_stop_cycle(EPS_MAX_DEELP_SLEEP);//静默模式
		system_entry_deep_sleep(0);//继续睡觉
	}
	else if(info->vbat < 3)//电量不足了
	{
		status = get_rtc_system_event_bit(EVT_SHOW_BATLOW);
		if(status == FALSE)//没有显示低电压才重新显示
		{
			send_epd_mail(EPD_EVT_BATAlA);//事件查询
		}
	}
	else if(info->vbat > 99)//电量恢复要清除
	{
		status = get_rtc_system_event_bit(EVT_SHOW_BATLOW);
		if(status == TRUE)//显示了电池图标
		{
			set_rtc_system_event_bit(EVT_SHOW_BATLOW, FALSE);//解除低电压报警提示
			send_epd_mail(EPD_EVT_FULL);//整屏显示
			return TRUE;
		}
	}
	else
	{
		//printf("is_refrsh_epd\r\n");
		return is_refrsh_epd();//检测屏幕是否需要刷新
	}
	return FALSE;//没有任何处理
}



/* --------------------------------------------------------------------------*/
/**
 * @Synopsis 显示当前时间戳 
 *
 * @Param now
 */
/* ----------------------------------------------------------------------------*/
void date_show(time_t now)
{

}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis 显示当前系统时间 
 *
 * @Returns  当前时间戳 
 */
/* ----------------------------------------------------------------------------*/
u32_t cur_date_show(void)
{
	return sysdate;
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  更新RTC的值
 *
 * @Param date 时间戳
 */
/* ----------------------------------------------------------------------------*/
void update_rtc_value(u32_t date)
{
	sysdate = date;
	system_rtc_mem_write(RTC_USEADDR1,&sysdate,sizeof(sysdate));
}


/* --------------------------------------------------------------------------*/
/**
 * @Synopsis 保证每天必须刷新一次屏幕
 */
/* ----------------------------------------------------------------------------*/
void cycle_update_show(void)
{

}



void entry_work_task(u8_t flag)
{
	taskWork |= flag;
}

void exit_work_task(u8_t flag)
{
	taskWork &= (~flag);
}

u8_t is_entry_sleep(void)
{
	//printf("task work=%x",taskWork);
	return taskWork;
}

static u32_t update_ask_time = RTC_ALARM_WAKEUP_TIME;

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  更新询问周期 
 *
 * @Returns   返回周期字段 
 */
/* ----------------------------------------------------------------------------*/
u32_t* update_ask_cycle_get(void)
{
	return &update_ask_time;
}

void set_system_stop_cycle(u32_t value)
{
	update_ask_time = value;
}

BOOL is_update_NoAP_hint(void)
{
	u16_t wakeup;

	wakeup = load_bkp_askfail_num();//询问失败数量
	if(wakeup > 0)
	{
		return FALSE;
	}
	return TRUE;
}


void delay_update_ask_time(u32 value)
{
	u16_t wakeup;

	wakeup = load_bkp_askfail_num();//询问失败数量
	if((update_ask_time == 60) && (wakeup < 3))//实时更新，前两次不增加延时。
	{

	}
	else
	{
		update_ask_time += (value*wakeup);//递增
	}
	
	if(update_ask_time > 24*3600)//本次睡眠时间大于1天，清零失败次数刷新屏幕维持显示
	{
		wakeup = 0;
		save_bkp_askfail_num(wakeup);
	}
}


void system_entry_deep_sleep(u32 value)
{
	#ifndef USING_SEC_MODE
	wifi_station_disconnect();//断开连接
	epd_module_close();
	sleep_gpio_epd_config();

	if(value != 0)
	{
		if(update_ask_time < (3600*3))
		{
			delay_update_ask_time(value);//延长休眠
		}
		else if(update_ask_time < (3600*24))//如果，更新时间小于2小时在异常情况下累计到8个小时唤醒一次
		{
			delay_update_ask_time(value);//延长休眠
		}
	}
	printf("Deep Sleep: %d S\r\n",update_ask_time);
	vTaskDelay(10 / portTICK_RATE_MS);
	SET_PERI_REG_MASK(UART_CONF0(0), UART_TXFIFO_RST);//RESET FIFO
	CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_TXFIFO_RST);
	system_deep_sleep_set_option(0);
	if(update_ask_time == SILENT_MODE_VALUE)//静默模式
	{
		system_deep_sleep(0);
		system_deep_sleep_instant(0);
	}
	else if(update_ask_time > EPS_MAX_DEELP_SLEEP)
	{
		update_ask_time = EPS_MAX_DEELP_SLEEP;
	}
	system_deep_sleep(1000000*update_ask_time);
	system_deep_sleep_instant(1000000*update_ask_time);
	#else
	vTaskDelay(1000*update_ask_time / portTICK_RATE_MS);
	update_event_mail(PRO_EVT_ASK);
	#endif
}


static void scan_done(void *arg, STATUS status)
{
	uint8 *ssid;

	ssid = calloc(1, 33);
	OS_ASSERT(ssid);
	
	if (status == OK)
	{
		printf("scan done ok\r\n");
		struct bss_info *bss_link = (struct bss_info *)arg;

		if(bss_link != NULL)//arg参数是扫描结果，不做判断会出现崩溃情况。
		{
			memset(ssid, 0, 33);
			if (strlen(bss_link->ssid) <= 32)
			{
				memcpy(ssid, bss_link->ssid, strlen(bss_link->ssid));
			}		
			else
			{
				memcpy(ssid, bss_link->ssid, 32);
			}
			
			printf("==============(%d,\"%s\",%d,\""MACSTR"\",%d)\r\n",
			bss_link->authmode, ssid, bss_link->rssi,
			MAC2STR(bss_link->bssid),bss_link->channel);
			devInfoDat.csq = (bss_link->rssi+113)/2;
			printf("CSQ = %d\n",devInfoDat.csq);
		}	
	}
	else
	{
		printf("scan fail !!!\r\n");
	}

	free(ssid);
}

void setWIFIConfigDat(const char *ssid,const char *password)
{
	strcpy(wifiConfigDat.ssid, ssid);
	strcpy(wifiConfigDat.password,password);
}


void get_wifi_intension(void)
{
	/*
	struct scan_config *scanConfig;
	struct station_config *stationConfig;
	BOOL result;

	scanConfig = calloc(1,sizeof(*stationConfig));
	OS_ASSERT(scanConfig);
	stationConfig = calloc(1, sizeof(*stationConfig));
	OS_ASSERT(stationConfig);
	
	result = wifi_station_get_config_default(stationConfig);
	printf("Get WIFI RSSI %s len=%d\r\n",stationConfig->ssid,strlen(stationConfig->ssid));
	if(strlen(stationConfig->ssid) > 0)
	{
		result = TRUE;
	}
	else
	{
		result = FALSE;
	}
	if(result == TRUE)
	{
		scanConfig->ssid = stationConfig->ssid;
		wifi_station_scan(scanConfig,scan_done);
	}
	else
	{
		printf("Get Station Config Fail\r\n");
	}

	free(scanConfig);
	free(stationConfig);*/
	devInfoDat.csq = (wifi_station_get_rssi()+113)/2;
	printf("CSQ = %d\n",devInfoDat.csq);
}


wifiConfigDef* getWIFIConfigDat(void)
{
	return &wifiConfigDat;
}


